package at.ac.tuwien.mg;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Vector;

import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;

import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;

import at.ac.tuwien.mg.bean.Item;
import at.ac.tuwien.mg.bean.Offer;
import at.ac.tuwien.mg.bean.OfferVector;
import at.ac.tuwien.mg.bean.Order;

/*
 * Wraps (and somewhat simplifies) Activiti-API functions.
 */
@ManagedBean(name="activiti")
@ApplicationScoped
public class Activiti implements Serializable {

	private static final long serialVersionUID = -6879505154149365799L;

	private ProcessEngine processEngine;
	private RepositoryService repositoryService;
	private RuntimeService runtimeService;
	private TaskService taskService;
	private ManagementService managementService;
	private IdentityService identityService;
	private HistoryService historyService;
	private FormService formService;

	public final String CONFIG = "config/activiti.cfg.xml";
	public final String PROC_DEF = "diagrams/Order_Submit.bpmn";
	private static final String PROC_DEF_ID = "OrderProcess";
	private static final String RULE_DEF = "rankoffers.drl";

	/**
	 * Quite unsurprisingly, the constructor starts Activiti and deploys the
	 * procurement process definition. Also, it sets all the members of this
	 * class for using them later.
	 */
	public Activiti() {

		processEngine = ProcessEngineConfiguration
				.createProcessEngineConfigurationFromResource(CONFIG)
				.buildProcessEngine();
		repositoryService = processEngine.getRepositoryService();
		runtimeService = processEngine.getRuntimeService();
		taskService = processEngine.getTaskService();
		managementService = processEngine.getManagementService();
		identityService = processEngine.getIdentityService();
		historyService = processEngine.getHistoryService();
		formService = processEngine.getFormService();

		List<Deployment> deployments = repositoryService
				.createDeploymentQuery().deploymentId(PROC_DEF).list();
		if (deployments == null || deployments.size() == 0) {
			DeploymentBuilder builder = repositoryService.createDeployment();
			builder.addClasspathResource(PROC_DEF);
			builder.addClasspathResource(RULE_DEF);
			builder.name(PROC_DEF);
			builder.deploy();
			System.out.println("Process deployed!");
		}
		// repositoryService.createDeployment().addClasspathResource(PROC_DEF).deploy();

	}

	/**
	 * Stops the Activiti engine. Be sure to call it after you are done.
	 */
	public void stop() {
		processEngine.close();
	}

	/**
	 * Creates a new procurement process instance.
	 * 
	 * @return Id of the created instance.
	 */
	public String newOrderProcess() {
		String[] itemList2 = {"wood", "stone", "silver", "gold"};
		Map<String, String> paramValues = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
		List<Item> itemList = new ArrayList<Item>();
		
		
		
		for (String i : itemList2) {
			itemList.add(new Item(i, Integer.parseInt(paramValues.get("orderform:"+i))));
			System.out.println(i + ": " + paramValues.get("orderform:"+i));
		}
		
		Order newOrder = new Order(itemList);
		Map<String, Object> varMap = new HashMap<String, Object>();
		
		/// Test purposes for rule task ///////
		//Vector<Offer> offerList = new Vector<Offer>();
		//for(int i=0; i<10; i++) {
			//offerList.add(new Offer("Supplier"+i,"wood",i));
		//}
		
		varMap.put("currentOrder", newOrder);
		varMap.put("throwError", true);	// juraj: need this to show that booking error handling works
		//varMap.put("recievedOffers", new OfferVector(offerList));
		
		runtimeService.startProcessInstanceByKey(PROC_DEF_ID, varMap);
		
		
		
		return "inbox";
	}
	
	public String redirectToTask(String id) {
		return getFormService().getTaskFormData(id).getFormKey();
	}

	public ProcessEngine getProcessEngine() {
		return processEngine;
	}

	public void setProcessEngine(ProcessEngine processEngine) {
		this.processEngine = processEngine;
	}

	public RepositoryService getRepositoryService() {
		return repositoryService;
	}

	public void setRepositoryService(RepositoryService repositoryService) {
		this.repositoryService = repositoryService;
	}

	public RuntimeService getRuntimeService() {
		return runtimeService;
	}

	public void setRuntimeService(RuntimeService runtimeService) {
		this.runtimeService = runtimeService;
	}

	public TaskService getTaskService() {
		return taskService;
	}

	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}

	public ManagementService getManagementService() {
		return managementService;
	}

	public void setManagementService(ManagementService managementService) {
		this.managementService = managementService;
	}

	public IdentityService getIdentityService() {
		return identityService;
	}

	public void setIdentityService(IdentityService identityService) {
		this.identityService = identityService;
	}

	public HistoryService getHistoryService() {
		return historyService;
	}

	public void setHistoryService(HistoryService historyService) {
		this.historyService = historyService;
	}

	public FormService getFormService() {
		return formService;
	}

	public void setFormService(FormService formService) {
		this.formService = formService;
	}

}
